#include "market_data/ctp_market_data.h"
#include "market_data/market_data_types.h"
#include <spdlog/spdlog.h>
#include <cstring>

namespace hft {

CtpMarketDataReceiver::CtpMarketDataReceiver() = default;
CtpMarketDataReceiver::~CtpMarketDataReceiver() { stop(); }

bool CtpMarketDataReceiver::init(const YAML::Node& config) {
    config_ = config;
    const auto& ctp_cfg = config["trading"]["market_data"]["provider"]["ctp"];
    front_address_ = ctp_cfg["front_address"].as<std::string>();
    user_id_ = ctp_cfg["user_id"].as<std::string>();
    password_ = ctp_cfg["password"].as<std::string>();
    broker_id_ = ctp_cfg["broker_id"].as<std::string>();
    app_id_ = ctp_cfg["app_id"].as<std::string>();
    auth_code_ = ctp_cfg["auth_code"].as<std::string>();
    return true;
}

bool CtpMarketDataReceiver::start() {
    if (api_) return true;
    api_.reset(CThostFtdcMdApi::CreateFtdcMdApi());
    callback_ = std::make_unique<CtpCallback>(this);
    api_->RegisterSpi(callback_.get());
    api_->RegisterFront(const_cast<char*>(front_address_.c_str()));
    api_->Init();
    spdlog::info("CTP MarketDataReceiver started.");
    return true;
}

void CtpMarketDataReceiver::stop() {
    if (api_) {
        api_->RegisterSpi(nullptr);
        api_->Release();
        api_.reset();
        callback_.reset();
        spdlog::info("CTP MarketDataReceiver stopped.");
    }
}

bool CtpMarketDataReceiver::subscribe(const std::string& symbol) {
    if (!api_) return false;
    char* instruments[1];
    instruments[0] = const_cast<char*>(symbol.c_str());
    int ret = api_->SubscribeMarketData(instruments, 1);
    spdlog::info("SubscribeMarketData: {} ret={}", symbol, ret);
    return ret == 0;
}

bool CtpMarketDataReceiver::unsubscribe(const std::string& symbol) {
    if (!api_) return false;
    char* instruments[1];
    instruments[0] = const_cast<char*>(symbol.c_str());
    int ret = api_->UnSubscribeMarketData(instruments, 1);
    spdlog::info("UnSubscribeMarketData: {} ret={}", symbol, ret);
    return ret == 0;
}

// --- CtpCallback ---
CtpMarketDataReceiver::CtpCallback::CtpCallback(CtpMarketDataReceiver* receiver)
    : receiver_(receiver) {}

void CtpMarketDataReceiver::CtpCallback::OnFrontConnected() {
    spdlog::info("CTP Front Connected");
    // 登录请求
    CThostFtdcReqUserLoginField req{};
    std::strncpy(req.BrokerID, receiver_->broker_id_.c_str(), sizeof(req.BrokerID)-1);
    std::strncpy(req.UserID, receiver_->user_id_.c_str(), sizeof(req.UserID)-1);
    std::strncpy(req.Password, receiver_->password_.c_str(), sizeof(req.Password)-1);
    receiver_->api_->ReqUserLogin(&req, 1);
}

void CtpMarketDataReceiver::CtpCallback::OnFrontDisconnected(int reason) {
    spdlog::warn("CTP Front Disconnected, reason={}", reason);
    receiver_->connected_ = false;
    receiver_->logged_in_ = false;
}

void CtpMarketDataReceiver::CtpCallback::OnRspUserLogin(CThostFtdcRspUserLoginField* pRspUserLogin,
    CThostFtdcRspInfoField* pRspInfo, int request_id, bool is_last) {
    if (pRspInfo && pRspInfo->ErrorID == 0) {
        spdlog::info("CTP User Login Success");
        receiver_->logged_in_ = true;
    } else {
        spdlog::error("CTP User Login Failed: {}", pRspInfo ? pRspInfo->ErrorMsg : "null");
        receiver_->logged_in_ = false;
    }
}

void CtpMarketDataReceiver::CtpCallback::OnRspSubMarketData(
    CThostFtdcSpecificInstrumentField* pSpecificInstrument,
    CThostFtdcRspInfoField* pRspInfo, int request_id, bool is_last) {
    if (pRspInfo && pRspInfo->ErrorID == 0) {
        spdlog::info("Subscribed to {}", pSpecificInstrument->InstrumentID);
    } else {
        spdlog::error("Subscribe failed: {}", pRspInfo ? pRspInfo->ErrorMsg : "null");
    }
}

void CtpMarketDataReceiver::CtpCallback::OnRtnDepthMarketData(CThostFtdcDepthMarketDataField* pDepthMarketData) {
    if (!pDepthMarketData) return;
    std::string symbol = pDepthMarketData->InstrumentID;
    MarketDataMessage msg;
    msg.symbol = symbol;
    msg.last_price = pDepthMarketData->LastPrice;
    msg.high_price = pDepthMarketData->HighestPrice;
    msg.low_price = pDepthMarketData->LowestPrice;
    msg.close_price = pDepthMarketData->ClosePrice;
    // 时间戳可进一步处理
    std::lock_guard<std::mutex> lock(receiver_->mutex_);
    receiver_->latest_data_[symbol] = msg;
    receiver_->historical_data_[symbol].push_back(msg);
    spdlog::info("CTP MarketData: {} last={}", symbol, msg.last_price);
}

MarketDataMessage CtpMarketDataReceiver::getLatestMarketData(const std::string& symbol) const {
    std::lock_guard<std::mutex> lock(mutex_);
    auto it = latest_data_.find(symbol);
    if (it != latest_data_.end()) {
        return it->second;
    }
    return MarketDataMessage{};
}

std::vector<MarketDataMessage> CtpMarketDataReceiver::getHistoricalMarketData(
    const std::string& symbol,
    const std::chrono::system_clock::time_point& start_time,
    const std::chrono::system_clock::time_point& end_time) const {
    std::vector<MarketDataMessage> result;
    std::lock_guard<std::mutex> lock(mutex_);
    auto it = historical_data_.find(symbol);
    if (it == historical_data_.end()) return result;
    for (const auto& msg : it->second) {
        if (msg.timestamp >= start_time && msg.timestamp <= end_time) {
            result.push_back(msg);
        }
    }
    return result;
}

} // namespace hft 